library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity adder_evo is
generic (	N : integer := 16;
		M : integer := 4);
port(	A	: in   std_logic_vector (N-1 downto 0);
		B	: in   std_logic_vector (N-1 downto 0);
		C_in	: in   std_logic;
		SUB	: in   std_logic;
		SIGN: in   std_logic;
		OVF	: out std_logic;
		S 	: out std_logic_vector (N-1 downto 0)
);
end adder_evo;

architecture Mixed of adder_evo is
component sparse_adder 
generic (	N : natural := 32;
		M : natural := 5 );					-- M = log2 (N)
port (	A	: in   std_logic_vector(N-1 downto 0);
		B 	: in   std_logic_vector(N-1 downto 0);
		Cin	: in   std_logic;
		S 	: out std_logic_vector(N-1 downto 0) ;
		Cout: out std_logic
);

end component;

signal i_B 		: std_logic_vector (N-1 downto 0);
signal i_S 		: std_logic_vector (N-1 downto 0);
signal i_carry_i	: std_logic;
signal i_carry_o	: std_logic;
signal i_OVF 		: std_logic;
begin

contol_section: process (A,B,C_in,SUB,SIGN,i_carry_o, i_S)
begin
-- SIGN=0,  A B unsigned
--  + OVF if A + B can't be stored in N bits
--  - OVF if B > A
-- SIGN=1,  A B 2's complement
--  A & B  != sign no OVF at all
--  A & B same sign and result has != sign, then OVF
	
	if SIGN = '0' then		-- unsigned numbers
		if SUB = '0' then			-- adder
			i_OVF 	<= i_carry_o;
			i_B 		<= B;
			i_carry_i	<= C_in;
		else						-- subtracter
			i_B 		<= not B;
			i_carry_i 	<= '1';
			
			if B > A then
				i_OVF 	<= '1';
			else
				i_OVF 	<= '0';
			end if;
		end if;
	else					-- CA2 numbers
		if SUB = '0' then			-- adder
			i_B		<= B;
			i_carry_i	<= C_in;
		else						-- subtracter
			i_B		<= not B;
			i_carry_i 	<= '1';
		end if;
								-- OVF is the same for both behaviours
		if A(N-1) /= i_B(N-1) then
			i_OVF 	<= '0';
		else
			if i_B(N-1) /= i_S(N-1) then
				i_OVF 	<= '1';
			else
				i_OVF 	<= '0' ;
			end if;
		end if;
	end if;

end process;

evo_core: sparse_adder generic map ( N,M) port
map (	A	=> A,
		B 	=> i_B,
		Cin	=> i_carry_i,
		S 	=> i_S,
		Cout=> i_carry_o
);

OVF	<= i_OVF;
S	<= i_S;

end Mixed;

